// GeneratorView implementation
// Copyright 2006 (C) Ralph Thomas

#include <view/gtk/generatorview.h>
#include <view/gtk/marshal.h>
#include <gdk/gdkkeysyms.h>

#include <stdio.h>

enum {
	SELECT_ALL,
	UNSELECT_ALL,
	SELECT_CURSOR_ITEM,
	TOGGLE_CURSOR_ITEM,
	MOVE_CURSOR,
	ACTIVATE_CURSOR_ITEM,
	LAST_SIGNAL
};

static guint generator_view_signals[LAST_SIGNAL] = { 0 };

static void		mission_generator_view_select_all			(MissionGeneratorView*	view);
static void		mission_generator_view_unselect_all			(MissionGeneratorView*	view);
static void		mission_generator_view_select_cursor_item	(MissionGeneratorView*	view);
static void		mission_generator_view_toggle_cursor_item	(MissionGeneratorView*	view);
static gboolean	mission_generator_view_activate_cursor_item	(MissionGeneratorView*	view);
static gboolean	mission_generator_view_move_cursor			(MissionGeneratorView*	view,
															 GtkMovementStep		step,
															 gint					count);
static void		gtk_icon_view_add_move_binding				(GtkBindingSet*			binding_set,
															 guint					keyval,
															 guint					modmask,
															 GtkMovementStep		step,
															 gint					count);
static void		mission_generator_view_realize				(GtkWidget           *widget);

G_DEFINE_TYPE (MissionGeneratorView, mission_generator_view, GTK_TYPE_WIDGET)

static void mission_generator_view_class_init (MissionGeneratorViewClass* klass) {
	GObjectClass*	gobject_class	= (GObjectClass*)klass;
	GtkWidgetClass*	widget_class	= GTK_WIDGET_CLASS (klass);
	GtkBindingSet*	binding_set		= 0;

	binding_set = gtk_binding_set_by_class (klass);

	widget_class->realize		= mission_generator_view_realize;

	klass->select_all			= mission_generator_view_select_all;
	klass->unselect_all			= mission_generator_view_unselect_all;
	klass->select_cursor_item	= mission_generator_view_select_cursor_item;
	klass->toggle_cursor_item	= mission_generator_view_toggle_cursor_item;
	klass->activate_cursor_item	= mission_generator_view_activate_cursor_item;
	klass->move_cursor			= mission_generator_view_move_cursor;

	generator_view_signals[SELECT_ALL] =
		g_signal_new( ("select_all"),
			G_TYPE_FROM_CLASS (gobject_class),
			G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
			G_STRUCT_OFFSET (MissionGeneratorViewClass, select_all),
			NULL, NULL,
			g_cclosure_marshal_VOID__VOID,
			G_TYPE_NONE, 0);

	generator_view_signals[UNSELECT_ALL] =
		g_signal_new( ("unselect_all"),
			G_TYPE_FROM_CLASS (gobject_class),
			G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
			G_STRUCT_OFFSET (MissionGeneratorViewClass, unselect_all),
			NULL, NULL,
			g_cclosure_marshal_VOID__VOID,
			G_TYPE_NONE, 0);

	generator_view_signals[SELECT_CURSOR_ITEM] =
		g_signal_new( ("select_cursor_item"),
			G_TYPE_FROM_CLASS (gobject_class),
			G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
			G_STRUCT_OFFSET (MissionGeneratorViewClass, select_cursor_item),
			NULL, NULL,
			g_cclosure_marshal_VOID__VOID,
			G_TYPE_NONE, 0);

	generator_view_signals[TOGGLE_CURSOR_ITEM] =
		g_signal_new( ("toggle_cursor_item"),
			G_TYPE_FROM_CLASS (gobject_class),
			G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
			G_STRUCT_OFFSET (MissionGeneratorViewClass, toggle_cursor_item),
			NULL, NULL,
			g_cclosure_marshal_VOID__VOID,
			G_TYPE_NONE, 0);

	generator_view_signals[ACTIVATE_CURSOR_ITEM] =
		g_signal_new( ("activate_cursor_item"),
			G_TYPE_FROM_CLASS (gobject_class),
			G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
			G_STRUCT_OFFSET (MissionGeneratorViewClass, activate_cursor_item),
			NULL, NULL,
			gtk_marshal_BOOLEAN__VOID,
			G_TYPE_BOOLEAN, 0);

	generator_view_signals[MOVE_CURSOR] =
		g_signal_new( ("move_cursor"),
			G_TYPE_FROM_CLASS (gobject_class),
			G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
			G_STRUCT_OFFSET (MissionGeneratorViewClass, move_cursor),
			NULL, NULL,
			g_cclosure_user_marshal_BOOLEAN__ENUM_INT,
			G_TYPE_BOOLEAN, 2,
			GTK_TYPE_MOVEMENT_STEP,
			G_TYPE_INT);

	//
	// key bindings, from gtk's gtkiconview.c (LGPL).
	//
	gtk_binding_entry_add_signal (binding_set, GDK_a, GDK_CONTROL_MASK, 
				"select_all", 0);
	gtk_binding_entry_add_signal (binding_set, GDK_a, GDK_CONTROL_MASK | GDK_SHIFT_MASK, 
				"unselect_all", 0);
	gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK, 
				"toggle_cursor_item", 0);

	gtk_binding_entry_add_signal (binding_set, GDK_space, 0, 
				"activate_cursor_item", 0);
	gtk_binding_entry_add_signal (binding_set, GDK_Return, 0, 
				"activate_cursor_item", 0);
	gtk_binding_entry_add_signal (binding_set, GDK_ISO_Enter, 0, 
				"activate_cursor_item", 0);
	gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0, 
				"activate_cursor_item", 0);

	gtk_icon_view_add_move_binding (binding_set, GDK_Up, 0,
				  GTK_MOVEMENT_DISPLAY_LINES, -1);
	gtk_icon_view_add_move_binding (binding_set, GDK_KP_Up, 0,
				  GTK_MOVEMENT_DISPLAY_LINES, -1);

	gtk_icon_view_add_move_binding (binding_set, GDK_Down, 0,
				  GTK_MOVEMENT_DISPLAY_LINES, 1);
	gtk_icon_view_add_move_binding (binding_set, GDK_KP_Down, 0,
				  GTK_MOVEMENT_DISPLAY_LINES, 1);

	gtk_icon_view_add_move_binding (binding_set, GDK_p, GDK_CONTROL_MASK,
				  GTK_MOVEMENT_DISPLAY_LINES, -1);

	gtk_icon_view_add_move_binding (binding_set, GDK_n, GDK_CONTROL_MASK,
				  GTK_MOVEMENT_DISPLAY_LINES, 1);

	gtk_icon_view_add_move_binding (binding_set, GDK_Home, 0,
				  GTK_MOVEMENT_BUFFER_ENDS, -1);
	gtk_icon_view_add_move_binding (binding_set, GDK_KP_Home, 0,
				  GTK_MOVEMENT_BUFFER_ENDS, -1);

	gtk_icon_view_add_move_binding (binding_set, GDK_End, 0,
				  GTK_MOVEMENT_BUFFER_ENDS, 1);
	gtk_icon_view_add_move_binding (binding_set, GDK_KP_End, 0,
				  GTK_MOVEMENT_BUFFER_ENDS, 1);

	gtk_icon_view_add_move_binding (binding_set, GDK_Page_Up, 0,
				  GTK_MOVEMENT_PAGES, -1);
	gtk_icon_view_add_move_binding (binding_set, GDK_KP_Page_Up, 0,
				  GTK_MOVEMENT_PAGES, -1);

	gtk_icon_view_add_move_binding (binding_set, GDK_Page_Down, 0,
				  GTK_MOVEMENT_PAGES, 1);
	gtk_icon_view_add_move_binding (binding_set, GDK_KP_Page_Down, 0,
				  GTK_MOVEMENT_PAGES, 1);

	gtk_icon_view_add_move_binding (binding_set, GDK_Right, 0, 
				  GTK_MOVEMENT_VISUAL_POSITIONS, 1);
	gtk_icon_view_add_move_binding (binding_set, GDK_Left, 0, 
				  GTK_MOVEMENT_VISUAL_POSITIONS, -1);

	gtk_icon_view_add_move_binding (binding_set, GDK_KP_Right, 0, 
				  GTK_MOVEMENT_VISUAL_POSITIONS, 1);
	gtk_icon_view_add_move_binding (binding_set, GDK_KP_Left, 0, 
				  GTK_MOVEMENT_VISUAL_POSITIONS, -1);
}

static void mission_generator_view_init (MissionGeneratorView* view) {}

static void
gtk_icon_view_add_move_binding (GtkBindingSet  *binding_set,
				guint           keyval,
				guint           modmask,
				GtkMovementStep step,
				gint            count)
{
  
	gtk_binding_entry_add_signal (binding_set, keyval, modmask,
                                ("move_cursor"), 2,
                                G_TYPE_ENUM, step,
                                G_TYPE_INT, count);

	gtk_binding_entry_add_signal (binding_set, keyval, GDK_SHIFT_MASK,
                                "move_cursor", 2,
                                G_TYPE_ENUM, step,
                                G_TYPE_INT, count);

	if ((modmask & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
		return;

	gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
                                "move_cursor", 2,
                                G_TYPE_ENUM, step,
                                G_TYPE_INT, count);

	gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK,
                                "move_cursor", 2,
                                G_TYPE_ENUM, step,
                                G_TYPE_INT, count);
}

static void		mission_generator_view_select_all			(MissionGeneratorView*	view) {}
static void		mission_generator_view_unselect_all			(MissionGeneratorView*	view) {}
static void		mission_generator_view_select_cursor_item	(MissionGeneratorView*	view) {}
static void		mission_generator_view_toggle_cursor_item	(MissionGeneratorView*	view) {}
static gboolean	mission_generator_view_activate_cursor_item	(MissionGeneratorView*	view) { return FALSE;}
static gboolean	mission_generator_view_move_cursor			(MissionGeneratorView*	view,
															 GtkMovementStep		step,
															 gint					count) { return TRUE; }

static void		mission_generator_view_realize				(GtkWidget           *widget) {
  MissionGeneratorView* view;
  GdkWindowAttr attributes;
  gint attributes_mask;

  g_return_if_fail (MISSION_IS_GENERATOR_VIEW (widget));

  view = MISSION_GENERATOR_VIEW (widget);
  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);

  attributes.window_type = GDK_WINDOW_CHILD;
  attributes.x = widget->allocation.x;
  attributes.y = widget->allocation.y;
  attributes.width = widget->allocation.width;
  attributes.height = widget->allocation.height;
  attributes.wclass = GDK_INPUT_OUTPUT;
  attributes.visual = gtk_widget_get_visual (widget);
  attributes.colormap = gtk_widget_get_colormap (widget);
  attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_ALL_EVENTS_MASK;

  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;

  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
  gdk_window_set_user_data (widget->window, view);

  widget->style = gtk_style_attach (widget->style, widget->window);
  gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
}

GtkWidget* mission_generator_view_new () {
	GtkWidget* w = g_object_new (MISSION_TYPE_GENERATOR_VIEW, NULL);
	GTK_WIDGET_SET_FLAGS(w, GTK_CAN_FOCUS);
	return w;
}

